#include "widget.h"
#include "ui_widget.h"

#include <QtCore>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    filename="C:/6tQzHr5mgbc_34.flv";
    qDebug() << filename;

    av_register_all();

    if(av_open_input_file(&formatCtx, filename.toLocal8Bit().constData(), NULL, 0, NULL)) {
        qDebug() << "Can't open video";
        return;
    }

    if(av_find_stream_info(formatCtx)<0) {
        qDebug() << "Can't find stream info";
    }

    dump_format(formatCtx, 0, filename.toLocal8Bit().constData(), false);

    videoStream=-1;
    for(unsigned int i=0; i<formatCtx->nb_streams; i++)
        if(formatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
            videoStream=i;
            break;
        }
    if(videoStream<0) {
        qDebug() << "No video stream.";
        return;
    }

    codecCtx=formatCtx->streams[videoStream]->codec;
    codec=avcodec_find_decoder(codecCtx->codec_id);
    if(!codec) {
        qDebug() << "Unsupported codec.";
        return;
    }

    ////codecCtx->time_base = (AVRational){1,30};

    if(avcodec_open(codecCtx, codec)<0) {
        qDebug() << "avcodec_open failed";
        return;
    }

    m_v_stream = formatCtx->streams[videoStream];

    //double v_time_base = 1.0 * v_stream->time_base.num / v_stream->time_base.den;
    qDebug() << "[formatCtx->duration]" << formatCtx->duration << QString("[%1 sec]").arg(formatCtx->duration / AV_TIME_BASE);
    qDebug()<< "[v_stream->start_time]"
            << m_v_stream->start_time
            ;
    qDebug()<< "[codecCtx->time_base]"
            << codecCtx->time_base.num
            << codecCtx->time_base.den
            << 1.0 * codecCtx->time_base.num / codecCtx->time_base.den
            << 1.0 / (1.0 * codecCtx->time_base.num / codecCtx->time_base.den)
            ;
    qDebug()<< "[v_stream->avg_frame_rate]"
            << m_v_stream->avg_frame_rate.num
            << m_v_stream->avg_frame_rate.den
            << 1.0 * m_v_stream->avg_frame_rate.num / m_v_stream->avg_frame_rate.den
            ;
    qDebug()<< "[v_stream->r_frame_rate]"
            << m_v_stream->r_frame_rate.num
            << m_v_stream->r_frame_rate.den
            << 1.0 * m_v_stream->r_frame_rate.num / m_v_stream->r_frame_rate.den
            ;
    qDebug()<< "[v_stream->time_base]"
            << m_v_stream->time_base.num
            << m_v_stream->time_base.den
            << 1.0 * m_v_stream->time_base.num / m_v_stream->time_base.den
            ;

    frame=avcodec_alloc_frame();
    m_av_picture = new T_AVPicture(PIX_FMT_BGRA, this->width(), this->height());

    frameNo=0;
    m_drop_count = 0;

    connect(&m_timer, SIGNAL(timeout()), SLOT(onTimerTimeout()));

    this->setWindowTitle(filename);
    this->resize(codecCtx->width, codecCtx->height);

    m_timer.start(33);
    m_fps1.wake();
    m_fps2.wake();
}

Widget::~Widget()
{
    delete ui;

    delete m_av_picture;
    av_free(frame);
    avcodec_close(codecCtx);
    av_close_input_file(formatCtx);
}

void Widget::onTimerTimeout()
{
    //qDebug() << "[Widget::onTimerTimeout()]";
    while(av_read_frame(formatCtx, &packet)>=0) {
        if(packet.stream_index!=videoStream)
        {
            av_free_packet(&packet);
            continue;
        }
        avcodec_decode_video(codecCtx, frame, &frameFinished, packet.data, packet.size);
        if(frameFinished) {
            frameNo++;
            //qDebug() << "m_time_line.isNull()" << m_time_line.isNull();
            //qDebug() << "m_time_line.isValid()" << m_time_line.isValid();
            m_fps1.add(1);
            if(m_time_line.isNull())
            {
                m_time_line.start();
            }
            //qDebug() << "m_time_line.elapsed()" << m_time_line.elapsed();
            if(packet.pts < m_time_line.elapsed())
            {
                //qDebug() << "=====>SKIP[frameNo]" << frameNo << "[packet.pts]" << packet.pts;
                m_drop_count++;
                continue;
            }
            else
            {
                //qDebug() << "          [frameNo]" << frameNo << "[packet.pts]" << packet.pts;
                m_fps2.add(1);
            }
#if 0x0
            qDebug()<< "[codecCtx->time_base]"
                    << codecCtx->time_base.num
                    << codecCtx->time_base.den
                    << 1.0 * codecCtx->time_base.num / codecCtx->time_base.den
                    << 1.0 / (1.0 * codecCtx->time_base.num / codecCtx->time_base.den)
                    ;
            qDebug()<< "[v_stream->r_frame_rate]"
                    << m_v_stream->r_frame_rate.num
                    << m_v_stream->r_frame_rate.den
                    << 1.0 * m_v_stream->r_frame_rate.num / m_v_stream->r_frame_rate.den
                    ;
#endif
            //if(frameNo > 30) goto skip;
            {
                m_av_picture->resize(this->width(), this->height());
                SwsContext *v_sws_ctx = sws_getContext(
                        codecCtx->width, //int srcW,
                        codecCtx->height, //int srcH,
                        codecCtx->pix_fmt, //enum PixelFormat srcFormat,
                        m_av_picture->m_width, //int dstW,
                        m_av_picture->m_height, //int dstH,
                        m_av_picture->m_pix_fmt, //enum PixelFormat dstFormat,
                        SWS_BICUBIC, //int flags,
                        NULL, //SwsFilter *srcFilter,
                        NULL, //SwsFilter *dstFilter,
                        NULL  //const double *param
                        );
                //qDebug() << v_sws_ctx;
                int v_scale_result = sws_scale(
                        v_sws_ctx,
                        frame->data,
                        frame->linesize,
                        0,
                        codecCtx->height,
                        m_av_picture->m_av_picture.data,
                        m_av_picture->m_av_picture.linesize
                        );
                //qDebug() << "[v_scale_result]" << v_scale_result;
                sws_freeContext(v_sws_ctx);
                QImage v_img(
                        m_av_picture->m_av_picture.data[0],
                        m_av_picture->m_width,
                        m_av_picture->m_height,
                        QImage::Format_ARGB32
                        );
                //qDebug() << img.isNull();
                m_displayBuffer = v_img;
            }
            skip:
            QWidget::update();
        }
        av_free_packet(&packet);
        break;
    }
}
